﻿/*-------------------------------------------------------------------------
* 命名空间: SiliconSelect.Common/SocketClient
* 类       名: SocketClient
* 功      能:  TD
* 时      间:  2023/9/18 13:03:47
* 版      本:  V1.0
* 作      者:  Fioman
* 格      言:  Talk is cheap,show me the code ^_^
*-------------------------------------------------------------------------*/
using DocumentFormat.OpenXml.Office.SpreadSheetML.Y2022.PivotVersionInfo;
using OfficeOpenXml.Drawing.Controls;
using SiliconSelect.Base;
using SiliconSelect.BLL;
using SiliconSelect.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;

namespace SiliconSelect.Common
{
    public class SocketClient
    {
        public SocketClient(SlaveState slaveState)
        {
            _slaveState = slaveState;
            if (_slaveState.SlaveName!.Contains("电阻率"))
            {
                _clientName = "电阻率";
            }
            _clientIp = _slaveState.IP!;
            _clientPort = _slaveState.Port;

        }

        public int DisConnectedCount = 0;

        private bool _isAlive;
        public SlaveState _slaveState;
        private string? _clientName;
        private string _clientIp;
        private int _clientPort;
        private int lastSelfPnId = -1; // 上一次的PNId
        private int lastSelfValId = -1; // 上一次的电阻率Id

        public TcpClient tcpClientConnected = new TcpClient(); // 创建

        public async Task StartClientAsync(CancellationTokenSource tokenParent)
        {
            tcpClientConnected.SendTimeout = 1000;
            try
            {
                while (!tokenParent.IsCancellationRequested)
                {
                    if (tcpClientConnected.ConnectAsync(_clientIp, _clientPort).Wait(2000))
                    {
                        _slaveState.ConnectedStatus = "已连接";
                        DisConnectedCount = 0;
                        LogHelper.WriteLogNapons(LogType.Info, "电阻率设备连接成功,开始接受消息");
                        await AcceptSeverMsgAsync(tokenParent);
                    }
                }

            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(LogType.Exception, $"电阻率连接失败: 失败原因: {ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!)}");
            }
        }


        /// <summary>
        /// 缓存消息,一条完整的消息必须包含\r\n
        /// </summary>
        private string msgRecvCache = "";
        private string singMsg = "";

        // 就是电阻率里面的数据要到一个事件戳,如果超过了一定的时间,比如说是1秒中,就认为这个流水号肯定是错误的.

        private async Task AcceptSeverMsgAsync(CancellationTokenSource tokenParent)
        {
            try
            {
                using (NetworkStream stream = tcpClientConnected?.GetStream()!)
                {
                    byte[] buffer = new byte[1024];
                    int bytesRead;
                    string? pnVal = "";
                    while (!tokenParent.IsCancellationRequested)
                    {
                        bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
                        if (tokenParent.IsCancellationRequested)
                        {
                            stream.Close();
                            break;
                        }
                        if (bytesRead == 0)
                        {
                            _isAlive = false;
                            _slaveState.ConnectedStatus = "已断开";
                            stream.Close();
                            LogHelper.WriteLog(LogType.Warn, $" {_clientName} 接收到数据长度为0,连接已断开,接收消息任务关闭!");
                            break;
                        }
                        string msgRec = Encoding.ASCII.GetString(buffer, 0, bytesRead);
                        msgRecvCache += msgRec; // 拼接到一起.
                        msgRecvCache = Regex.Replace(msgRecvCache, @"[\r]", "!");
                        if (!msgRecvCache.Contains('!'))
                        {
                            continue;
                        }
                        List<string> msgArr = msgRecvCache.Split('!').ToList();
                        for (int i = 0; i < msgArr.Count; i++)
                        {
                            if (msgArr[i].Contains("CMPND"))
                            {
                                //LogHelper.WriteLog(LogType.Info, $"from {_clientName} 接收到Pn值:  {msgArr[i]}");
                                singMsg = msgArr[i];
                                // 获取内部Id,如果和上一次的一样,就忽略
                                List<string> pnValList = msgArr[i].Replace("CMPND", "X").Split(",").ToList();
                                if (pnValList.Count > 10)
                                {
                                    if (lastSelfPnId == -1 && int.TryParse(pnValList[2].ToString(), out int pnId))
                                    {
                                        lastSelfPnId = pnId;
                                    }
                                    else
                                    {
                                        if (int.TryParse(pnValList[2], out int pnId02))
                                        {
                                            if (pnId02 == lastSelfPnId)
                                            {
                                                LogHelper.WriteLogSlave(LogType.Info, $"from {_clientName} 接收到重复消息,自动过滤掉:  {msgArr[i]}", _clientName);
                                                continue; // 如果发现pn值的Id重复了,就自动过滤掉重复消息
                                            }
                                            else
                                            {
                                                lastSelfPnId = pnId02; // 如果发现不重复就赋值
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    LogHelper.WriteLogSlave(LogType.Info, $"from {_clientName} 接收到无效消息,自动过滤掉:  {msgArr[i]}", _clientName);
                                    continue;
                                }
                                LogHelper.WriteLogSlave(LogType.Info, $"from {_clientName} 接收到Pn值:  {msgArr[i]}", _clientName);
                                if (pnValList.Contains("P"))
                                {
                                    pnVal = "P";
                                }
                                else if (pnValList.Contains("N"))
                                {
                                    pnVal = "N";
                                }
                                else
                                {
                                    pnVal = "E";
                                }
                            }
                            if (msgArr[i].Contains("CMESD"))
                            {
                                List<string> valList = msgArr[i].Split(",").ToList();
                                List<string> resList;
                                int lastIndex = valList.FindLastIndex(item => item.Contains("CMESD"));
                                if (lastIndex != -1)
                                {
                                    resList = valList.GetRange(lastIndex, valList.Count - lastIndex);
                                }
                                else
                                {
                                    resList = valList;
                                }
                                resList[0] = "CMESD"; // 将首位改成这样的
                                if (resList.Count > 10)
                                {
                                    if (lastSelfValId == -1 && int.TryParse(resList[3], out int valId))
                                    {
                                        lastSelfValId = valId;
                                    }
                                    else
                                    {
                                        if (int.TryParse(resList[3], out int valId02))
                                        {
                                            if (valId02 == lastSelfValId)
                                            {
                                                LogHelper.WriteLogSlave(LogType.Info, $"from {_clientName} 接收到重复消息,自动过滤掉:  {msgArr[i]}", _clientName);
                                                continue; // 如果发现电阻率的id值的Id重复了,就自动过滤掉重复消息
                                            }
                                            else
                                            {
                                                lastSelfValId = valId02; // 如果发现不重复就赋值
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    LogHelper.WriteLogSlave(LogType.Info, $"from {_clientName} 接收到无效消息,自动过滤掉:  {msgArr[i]}", _clientName);
                                    continue;
                                }
                                LogHelper.WriteLogSlave(LogType.Info, $"from {_clientName} 接收到电阻率值:  {string.Join(',', resList)}", _clientName);
                                //LogHelper.WriteLog(LogType.Info, $"from {_clientName} 接收到电阻率值:  {msgArr[i]}");
                                ParseMsgFromResistivity(resList, pnVal);
                            }
                        }
                        if (!string.IsNullOrEmpty(msgArr[msgArr.Count - 1]))
                        {
                            msgRecvCache += msgArr[msgArr.Count - 1];
                        }
                        else
                        {
                            msgRecvCache = "";
                        }

                        ////if (msgRecvCache.Contains("CMESD") && msgRecvCache.Contains("CMPND") && msgRecvCache.LastIndexOf('!') > msgRecvCache.LastIndexOf("CMESD"))
                        ////{

                        ////    //// 1. 先將消息按照CMPND分隔，选取第一个.如果后面还有数据.要继续累加
                        ////    //List<string> msgArr = msgRecvCache.Split("CMPND").ToList();
                        ////    //msgRecvCache = "";
                        ////    //for (int i = 0; i < msgArr.Count; i++)
                        ////    //{
                        ////    //    if (string.IsNullOrEmpty(msgArr[i]))
                        ////    //    {
                        ////    //        continue;
                        ////    //    }
                        ////    //    if (msgArr[i].Contains("CMESD"))
                        ////    //    {
                        ////    //        string msgParse = "CMPND" + msgArr[i];
                        ////    //        ParseMsgFromResistivity(msgParse, "PC");
                        ////    //    }
                        ////    //    else
                        ////    //    {
                        ////    //        msgRecvCache += msgArr[i];
                        ////    //    }
                        //   KKKKKKKKKKKKKKK
                        //}
                    }
                }
            }
            catch (IOException ex)
            {
                string msg = ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!);
                LogHelper.WriteLog(LogType.Exception, msg);
                // 处理网络中断等异常情况
            }
            catch (Exception ex)
            {
                string msg = ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!);
                LogHelper.WriteLog(LogType.Exception, msg);
                // 其他异常处理
            }
            finally
            {
                if (_isAlive)
                {
                    _isAlive = false;
                    _slaveState.ConnectedStatus = "已断开";
                    LogHelper.WriteLog(LogType.Info, $" {_clientName} 接收消息任务关闭!");
                }
                if (tcpClientConnected != null)
                {
                    tcpClientConnected?.Dispose();
                    tcpClientConnected?.Close();
                    tcpClientConnected = null!;
                }
            }
        }


        public void ParseMsgFromResistivity(List<string> msgPn, string pnVal)
        {
            try
            {
                //int indexStart = msgPn.IndexOf("CMPND");
                //double numer1 = Convert.ToDouble(msgPn[indexStart + 4]);
                //int number2 = Convert.ToInt32(msgPn[indexStart + 5]);
                //int number3 = Convert.ToInt32(msgPn[indexStart + 7]);
                //if (numer1 > number3 * 0.8)
                //{
                //    PnVal = "P";
                //}
                //else if (number2 > number3 * 0.8)
                //{
                //    PnVal = "N";
                //}
                //else
                //{
                //    PnVal = "E";
                //}

                int indexStart = msgPn.IndexOf("CMESD");
                double resistivityMax = Convert.ToDouble(msgPn[indexStart + 6]);
                double resistivityMin = Convert.ToDouble(msgPn[indexStart + 7]);
                double resistivityAver = Convert.ToDouble(msgPn[indexStart + 8]);
                string waferId = (GlobalValues.LastResistivityId + 1).ToString();
                string waferId02 = string.Empty;
                //double thicknessVal = 0.0;
                // 然后是根据厚度去计算,先获取流水号,然后根据流水号去获取厚度值.
                if (GlobalValues.WaferIdQueue.Count == 1 || GlobalValues.WaferIdQueue.Count == 2)
                {
                    waferId = GlobalValues.WaferIdQueue.Dequeue();
                }
                else if (GlobalValues.WaferIdQueue.Count > 3)
                {
                    // 把最近的两个保存,然后数据清空.重新来
                    LogHelper.WriteLog(LogType.Info, $"电阻率流水号队列为3个以上(取出最近的两个),具体个数为: {GlobalValues.WaferIdQueue.Count}");
                    var array = GlobalValues.WaferIdQueue.ToArray();
                    waferId = array[array.Length - 2]; // 获取最后一个流水号
                    waferId02 = array[array.Length - 1]; // 获取倒数第二个流水号
                    GlobalValues.WaferIdQueue.Clear();// 清空从新来.
                }
                else
                {

                    //LogHelper.WriteLogSlave(LogType.Fatal, $"电阻率结果没有收到对应流水号,此次结果不发,判定为碎片,当前流水号为: {waferId}", _clientName);
                    //return;
                    // 没有获取到对应的流水号,这里要判断3D是否也没有流水号,如果3D和电阻率都没有流水号就直接丢掉,这里3D工位在后面,所以这里的3D的map要编程了电阻率Map了.
                    LogHelper.WriteLogSlave(LogType.Fatal, $"电阻率结果没有收到对应流水号,厚度有流水号,使用上一次的流水号+1,使用流水号为: {waferId}", _clientName);
                    //GlobalValues.LastResistivityId = int.Parse(waferId); // 这里最后一个流水号也要更新一下.如果一直没有,就一直使用下一个. 这里不能更新,防止碎片.
                    // 如果是碎片之后,这里更新了,就收不到PLC的了,相当于是流水号提前了. 所以这里不更新.就用来防呆一次,就行了.如果连续出现2次,肯定就是有问题了.
                }
                //GlobalValues.LastResistivityId = int.Parse(waferId); // 更新最后一次的waferIds
                //if (GlobalValues.ThicknessMap.ContainsKey(waferId))
                //{
                //    thicknessVal = GlobalValues.ThicknessMap[waferId];
                //    GlobalValues.LastThickness = thicknessVal;
                //    GlobalValues.ThicknessMap.Remove(waferId);
                //}

                KeepMsgRecvFromWhere(waferId, _clientName!);
                // 将电阻率数据存放到队列中去,然后在3D数据获取到时候,重新保存电阻率数据
                GlobalValues.ResistivityValMap[waferId] = new Tuple<double, double, double, string>(resistivityMax, resistivityMin, resistivityAver, pnVal);
                LogHelper.WriteLogSlave(LogType.Info, $"流水号:{waferId},电阻率结果, 最大值: {resistivityMax}," +
                    $"最小值:{resistivityMin},平均值:{resistivityAver}, PN型:{pnVal}", _clientName);



                //string resistivityMaxShow = GetFinalValByKb(resistivityMax, thicknessVal);
                //string resistivityMinShow = GetFinalValByKb(resistivityMin, thicknessVal);
                //string resistivityAverShow = GetFinalValByKb(resistivityAver, thicknessVal);
                //List<int> maxLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.ResistivityMaxRule, resistivityMaxShow);
                //List<int> minLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.ResistivityMinRule, resistivityMinShow);
                //List<int> averLevel = CalcDetectedLevel.CalcDetectedLevelByRule(DetectedRuleHelper.ResistivityAverRule, resistivityAverShow);



                //// 如果没有屏蔽掉,并且等级在.
                //Dictionary<string, List<int>> levelMap = new Dictionary<string, List<int>>();
                //// 如果已经存在了,就不用赋值了.
                //if (GlobalValues.WaferIdLevelDictionary.ContainsKey(waferId))
                //{
                //    levelMap = GlobalValues.WaferIdLevelDictionary[waferId];
                //}
                //else
                //{
                //    GlobalValues.WaferIdLevelDictionary[waferId] = levelMap;
                //}
                //if (!GlobalValues.ModuleIsShield.Contains(_clientName!))
                //{
                //    if (maxLevel.Count > 0)
                //    {
                //        levelMap[$"{_clientName}_1"] = maxLevel;
                //    }
                //    if (minLevel.Count > 0)
                //    {
                //        levelMap[$"{_clientName}_2"] = minLevel;
                //    }
                //    if (averLevel.Count > 0)
                //    {
                //        levelMap[$"{_clientName}_3"] = averLevel;
                //    }
                //}



                // 数据库更新的时候,查询的字段(根据流水号产品Id和晶棒编号)
                //List<string> queryFields = new List<string>()
                //{
                //    "WaferId","CrystalNumber","CutNumber"
                //};

                //List<string> queryVals = new List<string>()
                //{
                //    waferId,GlobalValues.CrystalNumberCurrent!,GlobalValues.CrystalNumberCurrent!
                //};



                //List<string> updateFields = new List<string>();
                //List<string> updateVals = new List<string>();
                //updateFields.Add("ResistivityAver");
                //updateVals.Add(resistivityAverShow);
                //updateFields.Add("ResistivityMax");
                //updateVals.Add(resistivityMaxShow);
                //updateFields.Add("ResistivityMin");
                //updateVals.Add(resistivityMinShow);

                // 数据保存到全年局变量中去
                //string[] dataResistivity = new string[GlobalValues.ResistivityTitle.Length];
                //dataResistivity[0] = CsvHelper.GetNumberValForCsv(resistivityAverShow);
                //dataResistivity[1] = CsvHelper.GetNumberValForCsv(resistivityMaxShow);
                //dataResistivity[2] = CsvHelper.GetNumberValForCsv(resistivityMinShow);
                //GlobalValues.WaferDataResistivity[waferId] = dataResistivity;

                // 保存到全局变量中,方便国产电阻率使用
                //string[] naponsVal = new string[] { waferId, thicknessVal.ToString(), resistivityAverShow, resistivityMaxShow, resistivityMinShow, pnVal };
                //GlobalValues.NaponsResistivityQueue.Enqueue(naponsVal); // 放入队列中.

                //Task.Run(() =>
                //{
                //    DataResult res = LocalDataAccess.UpdateWaferDetectedDetailTb(queryFields, queryVals, updateFields, updateVals);
                //    if (!res.State)
                //    {
                //        LogHelper.WriteLog(LogType.Warn, $"电阻率数据写入到数据库中失败: {res.Message},此时的updateFields = {string.Join(',', updateFields)},updateVals = {string.Join(',', updateVals)}");
                //    }
                //});
                //DataResult res = MsgParseHelper.UpdateWaferIdSummaryTask(waferId);
                //if (!res.State)
                //{
                //    LogHelper.WriteLog(LogType.Warn, $"电阻率流水号对应更新时间添加到全局变量中失败: {res.Message}");
                //}


                //if (!string.IsNullOrEmpty(waferId02))
                //{
                //    KeepMsgRecvFromWhere(waferId02, _clientName!);
                //    GlobalValues.WaferDataResistivity[waferId02] = dataResistivity;
                //    naponsVal = new string[] { waferId02, thicknessVal.ToString(), resistivityAverShow, resistivityMaxShow, resistivityMinShow, pnVal };
                //    GlobalValues.NaponsResistivityQueue.Enqueue(naponsVal); // 放入队列中.

                //    //Task.Run(() =>
                //    //{
                //    //    DataResult res = LocalDataAccess.UpdateWaferDetectedDetailTb(queryFields, queryVals, updateFields, updateVals);
                //    //    if (!res.State)
                //    //    {
                //    //        LogHelper.WriteLog(LogType.Warn, $"电阻率数据写入到数据库中失败: {res.Message},此时的updateFields = {string.Join(',', updateFields)},updateVals = {string.Join(',', updateVals)}");
                //    //    }
                //    //});
                //    res = MsgParseHelper.UpdateWaferIdSummaryTask(waferId02);
                //    if (!res.State)
                //    {
                //        LogHelper.WriteLog(LogType.Warn, $"电阻率流水号对应更新时间添加到全局变量中失败: {res.Message}");
                //    }

                //    LogHelper.WriteLogSlave(LogType.Info, $"流水号:{waferId02},厚度:{thicknessVal},电阻率结果, 最大值: {resistivityMaxShow}," +
                //        $"最小值:{resistivityMinShow},平均值:{resistivityAverShow}, PN型:{pnVal}", _clientName);
                //}

            }
            catch (Exception ex)
            {

                LogHelper.WriteLogNapons(LogType.Fatal, ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!));
            }

        }

        private void KeepMsgRecvFromWhere(string waferId, string clientName)
        {
            List<string> listVal = new List<string>();
            if (GlobalValues.WaferIdFromPcDictionary.ContainsKey(waferId))
            {
                listVal = GlobalValues.WaferIdFromPcDictionary[waferId];
                listVal.Add(clientName);
            }
            else
            {
                listVal.Add(clientName);
            }
            GlobalValues.WaferIdFromPcDictionary[waferId] = listVal;
        }

        /// <summary>
        /// 根据K和B以及厚度去计算电阻率的值
        /// </summary>
        /// <param name="resistivityMax"></param>
        /// <param name="thicknessVal"></param>
        /// <returns></returns>
        private string GetFinalValByKb(double val, double thicknessVal)
        {
            try
            {
                double[] args = GlobalValues.VisionOffsetMap["NaponsNc"];
                return (args[0] * thicknessVal * val * 0.0001 + args[1]).ToString("f3");
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(LogType.Fatal, ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!));
                return "0";
            }
        }

        internal void StopClient()
        {
            if (tcpClientConnected != null)
            {
                tcpClientConnected.Dispose();
                tcpClientConnected.Close();
            }
        }
    }
}
